import messagetype.*;
import message.*;
import com.alibaba.fastjson.JSON;
import pojo.Group;
import pojo.Message;
import pojo.User;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * @author Administrator
 */
public class ServerThread implements Runnable {

    String userAccount = null;
    private Socket socket;
    Map<String, Socket> sockets = new HashMap<String, Socket>();
    int count;
    InputStream is;
    OutputStream os;
    DataInputStream din;
    DataOutputStream dou;

    public ServerThread(Socket client, Map<String, Socket> sockets, int count) throws IOException {
        this.socket = client;
        this.sockets = sockets;
        this.count = count;
        is = client.getInputStream();
        os = client.getOutputStream();
        din = new DataInputStream(is);
        dou = new DataOutputStream(os);
    }

    public void processClient() throws IOException {

        while (true) {
            MsHead msg = MsgTool.readMsgHead(din);
            byte type = msg.getType();
            //注册
            if (type == ByteType.REGISTER)
            {
                RegMsg rm = (RegMsg) msg;
                byte type1 = 0x05, state = 0;
                User user = JSON.parseObject(rm.getJsonStr(), User.class);
                User user1 = MainFunction.saveInformation(user);
                UserMapper userMapper = MainFunction.loadUserMapperXml();
                List<String> strings = userMapper.selectAccount(user1.getName());
                String s = strings.get(strings.size() - 1);
                user1.setAccount(s);
                String jsonStr = JSON.toJSONString(user1);
                RegResMsg rrm = new RegResMsg(6 + jsonStr.getBytes().length, type1, state, jsonStr);

                byte[] data = MsgTool.packMsg(rrm);
                dou.write(data);
                dou.flush();
            } //登录
            else if (type == ByteType.LOGIN_MESSAGE)
            {
                LoginMsg lm = (LoginMsg) msg;
                User user = JSON.parseObject(lm.getJsonStr(), User.class);
                boolean b = MainFunction.checkLogin(user);
                System.out.println(b);
                byte type1 = 0x06, state = 0;
                if (b == false) {
                    state = 1;
                    String str = "账号或密码错误";
                    LoginResMsg lrm = new LoginResMsg(6 + str.getBytes().length, type1, state, str);

                    byte[] data = MsgTool.packMsg(lrm);
                    dou.write(data);
                    dou.flush();
                } else {
                    userAccount = user.getAccount();
                    System.out.println("用户："+userAccount+"加入服务器");

                    sockets.put(user.getAccount(), socket);
                    UserMapper userMapper = MainFunction.loadUserMapperXml();
                    CompanionMapper companionMapper = MainFunction.loadCompanionMapperXml();

                    User user1 = userMapper.selevtUserbyAccount(user.getAccount());

                    System.out.println("用户信息：");
                    System.out.println("账号："+user1.getAccount());
                    System.out.println("名字："+user1.getName());
                    System.out.println("密码："+user1.getPassword());
                    System.out.println("当前在线人数："+Server.count);

                    List<Integer> integers = companionMapper.selectFriendsAccount(Integer.parseInt(user.getAccount()));
                    List<String> lists = new ArrayList<>();
                    for (int i : integers) {
                        lists.add(i + "");
                    }
                    user1.setFriends(lists);

                    List<Group>list = MainFunction.writeGroups(user1);
                    user1.setGroups(list);
                    String jsonStr = JSON.toJSONString(user1);

                    LoginResMsg lrm = new LoginResMsg(6 + jsonStr.getBytes().length, type1, state, jsonStr);

                    byte[] data = MsgTool.packMsg(lrm);
                    dou.write(data);
                    dou.flush();
                }
            }
            //私聊
            else if (type == ByteType.CHAT_MESSAGE)
            {
                ChatMsg cm = (ChatMsg) msg;
                privateChat(cm);
            }
            //保存注册用户头像
            else if (type == ByteType.SAVE_IMAGE_MESSAGE)
            {
                FileMsg fM = (FileMsg) msg;
                User user = JSON.parseObject(fM.getUser(), User.class);
                MainFunction.parseImage(socket, user);
                break;
            }
            //查找账号对应的用户信息
            else if (type == ByteType.FIND_USER_MESSAGE)
            {
                FindMsg fm = (FindMsg) msg;
                String str = fm.getInformation();
                UserMapper userMapper = MainFunction.loadUserMapperXml();
                User user = userMapper.selevtUserbyAccount(str);
                String information = JSON.toJSONString(user);
                int flag = fm.getFlag();
                FindMsg fm1 = new FindMsg(flag, 9 + information.getBytes().length, type, information);

                byte[] bytes = MsgTool.packMsg(fm1);
                dou.write(bytes);
                dou.flush();

            }
            //服务端返回图片
            else if (type == ByteType.FIND_IMAGE_MESSAGE)
            {
                FindImageMsg fim = (FindImageMsg) msg;
                String accountAndImage = fim.getAccountAndImage();
                AccountAndImage aai = JSON.parseObject(accountAndImage, AccountAndImage.class);

                String str = MainFunction.returnImage(aai.getAccount());
                aai.setImage(str);
                String accountAndImage1 = JSON.toJSONString(aai);
                FindImageMsg fim1 = new FindImageMsg(5 + accountAndImage1.getBytes().length,type,accountAndImage1);

                byte[] bytes = MsgTool.packMsg(fim1);
                dou.write(bytes);
                dou.flush();
            }
            //将该用户添加进入目标用户的好友申请列表
            else if (type == ByteType.ADD_FRIEND_MESSAGE)
            {
                AddFriendMsg afm = (AddFriendMsg) msg;
                UserToUser usertouser = JSON.parseObject(afm.getUserInformation(), UserToUser.class);
                if(MainFunction.judgeExist(usertouser.getSrcUser().getAccount(),usertouser.getDestUser().getAccount())==false) {
                    MainFunction.addNewFriend(usertouser.getSrcUser().getAccount(), usertouser.getDestUser().getAccount());
                }
            }
            //服务端返回好友申请列表
            else if (type == ByteType.FIND_FRIEND_RES_LIST_MESSAGE)
            {
                FindResList frl = (FindResList) msg;
                List<User> list = MainFunction.newFriendsMessage(frl.getUserInformation());
                String jsonList = JSON.toJSONString(list);
                FindResList frl1 = new FindResList(jsonList.getBytes().length + 5,type,jsonList);

                byte[] bytes = MsgTool.packMsg(frl1);
                dou.write(bytes);
                dou.flush();
            }
            //添加好友应答消息
            else if (type == ByteType.ADD_FRIEND_RES_MESSAGE)
            {
                AddFriendResMsg arm = (AddFriendResMsg) msg;
                UserToUser userToUser = JSON.parseObject(arm.getInformation(), UserToUser.class);
                byte state = arm.getState();
                if (state == 1) {
                    Socket socket1 = null;
                    MainFunction.addFriend(userToUser.getSrcUser().getAccount(), userToUser.getDestUser().getAccount());
                    for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
                        if (entry.getKey().equals(userToUser.getDestUser().getAccount())) {
                            socket1 = entry.getValue();
                        }
                    }
                    User user = userToUser.getSrcUser();
                    String str = JSON.toJSONString(user);
                    DataOutputStream dos = new DataOutputStream(socket1.getOutputStream());
                    AddFriendResMsg arm1 = new AddFriendResMsg(6 + str.getBytes().length, type, state, str);

                    byte[] bytes = MsgTool.packMsg(arm1);
                    dos.write(bytes);
                    dos.flush();
                }
                MainFunction.deleteMessage(userToUser.getDestUser().getAccount(), userToUser.getSrcUser().getAccount());
            }
            //好友消息
            else if (type == ByteType.FRIEND_MESSAGE_LIST)
            {
                FriendMsgList fml = (FriendMsgList) msg;
                User user = JSON.parseObject(fml.getMsgList(),User.class);
                List<Message>msgLst = MainFunction.getAllMessage(user.getAccount());
                String jsonMsg = JSON.toJSONString(msgLst);
                FriendMsgList fml1 = new FriendMsgList(5+jsonMsg.getBytes().length,type,jsonMsg);

                byte[] bytes = MsgTool.packMsg(fml1);
                dou.write(bytes);
                dou.flush();
            }
            //删除好友
            else if (type == ByteType.DELETE_FRIEND_MESSAGE)
            {
                DeleteFriendMsg dfm = (DeleteFriendMsg)msg;
                UserToUser user = JSON.parseObject(dfm.getInformation(),UserToUser.class);
                MainFunction.deleteFriend(user.getDestUser().getAccount());
                MainFunction.deleteMessage(user.getSrcUser().getAccount(),user.getDestUser().getAccount());

                Socket socket1 = null;
                for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
                    if (entry.getKey().equals(user.getDestUser().getAccount())) {
                        socket1 = entry.getValue();
                    }
                }
                DataOutputStream dos = new DataOutputStream(socket1.getOutputStream());

                byte[] bytes = MsgTool.packMsg(dfm);
                dos.write(bytes);
                dos.flush();
            }
            //创建群组
            else if (type == ByteType.BUILD_GROUP_MESSAGE)
            {
                CreateGroupMsg cgm = (CreateGroupMsg) msg;
                Group group = JSON.parseObject(cgm.getGroupInformation(), Group.class);

                System.out.println(group);
                String account = MainFunction.bulidGroup(group.getGroupName(), group.getHostAccount());
                System.out.println(account);
                group.setGroupAccount(account);

                byte[] b = ImgUtil.decode(group.getImage());
                FileOutputStream fos = new FileOutputStream("src/photo/" + group.getGroupAccount() + ".png");
                fos.write(b);
                String jsonGroup = JSON.toJSONString(group);
                CreateGroupMsg cgm1 = new CreateGroupMsg(jsonGroup.getBytes().length + 5, type, jsonGroup);

                byte[] bytes = MsgTool.packMsg(cgm1);
                dou.write(bytes);
                dou.flush();
            }
            //拉人进群
            else if (type == ByteType.ADD_USER_TO_GROUP_MESSAGE)
            {
                GroupMapper groupMapper = MainFunction.loadGroupMapper();
                UserMapper userMapper = MainFunction.loadUserMapperXml();
                AddUserToGroupMsg au = (AddUserToGroupMsg) msg;
                UserGroupToUser ug = JSON.parseObject(au.getInformation(),UserGroupToUser.class);
                System.out.println(ug.getGroup());
                MainFunction.saveGroup(ug.getGroup().getGroupAccount(),ug.getDestUser().getAccount());

                Socket socket1 = null;
                for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
                    if (entry.getKey().equals(ug.getDestUser().getAccount())) {
                        socket1 = entry.getValue();
                    }
                }
                if(socket1!=null) {
                    DataOutputStream dos = new DataOutputStream(socket1.getOutputStream());

                       //给被拉入者发送message
                    String str = null;
                    try {
                        str = ImgUtil.encodeImage("src/photo/" + ug.getGroup().getGroupAccount() + ".png");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    ug.getGroup().setImage(str);

                    String groupAccount = ug.getGroup().getGroupAccount();
                    ug.getGroup().setGroupName(groupMapper.getGroupName(groupAccount).get(0));
                    ArrayList<String> members = MainFunction.getMembers(groupAccount);
                    ArrayList<User> users = new ArrayList<>();
                    for (String string : members) {
                        User user = userMapper.selevtUserbyAccount(string);
                        users.add(user);
                    }
                    ug.getGroup().setMembers(users);
                    UserGroupToUser ug1 = new UserGroupToUser(ug.getDestUser(), ug.getGroup());
                    String group = JSON.toJSONString(ug1);

                    byte type1 = 0x16;
                    AddUserToGroupResMsg auto = new AddUserToGroupResMsg(5 + group.getBytes().length, type1, group);
                    byte[] bytes = MsgTool.packMsg(auto);
                    dos.write(bytes);
                    dos.flush();

                    UpdateList ul = new UpdateList(ug.getDestUser(),ug.getGroup());
                    updateMsg(ul, socket1, ul.getGroup().getGroupAccount(), 1);
                }//通知其他所有人更新

            }
            //群聊
            else if (type == ByteType.ALL_CHAT_MESSAGE)
            {
                TogetherChatMsg tt = (TogetherChatMsg)msg;
                togetherChat(tt);
            }
            //群聊消息
            else if (type == ByteType.GROUP_MESSAGE_LIST)
            {
                GroupMsgList gm = (GroupMsgList) msg;
                User user = JSON.parseObject(gm.getInformation(),User.class);

                List <Message> groupMsgList = MainFunction.getGroupMessage(user.getAccount());
                String groupMsg = JSON.toJSONString(groupMsgList);
                GroupMsgList gm1 = new GroupMsgList(5+groupMsg.getBytes().length,type,groupMsg);

                byte[] bytes = MsgTool.packMsg(gm1);
                dou.write(bytes);
                dou.flush();
            }
            //退出群聊
            else if (type == ByteType.EXIT_GROUP_MESSAGE)
            {
                ExitGroupMsg egm = (ExitGroupMsg) msg;
                ExitGroup eg = JSON.parseObject(egm.getGroupInformation(),ExitGroup.class);

                Socket socket1 = null;
                for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
                    if (entry.getKey().equals(eg.getUser().getAccount())) {
                        socket1 = entry.getValue();
                    }
                }
                System.out.println(eg.getGroup().getHostAccount());
                if(eg.getUser().getAccount().equals(eg.getGroup().getHostAccount())){
                    System.out.println(1);
                    MainFunction.hostExit(eg.getGroup().getGroupAccount());
                }
                else{
                    MainFunction.memberExit(eg.getUser().getAccount());
                }
                UpdateList ul = new UpdateList(eg.getUser(),eg.getGroup());
                updateMsg(ul,socket1,ul.getGroup().getGroupAccount(),0);
            }
        }
    }

    public void togetherChat(TogetherChatMsg tt) throws IOException {
        UserMsgToGroup um = JSON.parseObject(tt.getInformation(), UserMsgToGroup.class);
        ArrayList<String> members = MainFunction.getMembers(um.getGroupAccount());
        for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
            if(!entry.getValue().equals(socket)) {
                for (int i = 0; i < members.size(); i++) {
                    if (entry.getKey().equals(members.get(i))) {
                        DataOutputStream dos1 = new DataOutputStream(entry.getValue().getOutputStream());
                        byte[] bytes = MsgTool.packMsg(tt);
                        dos1.write(bytes);
                        dos1.flush();
                    }
                }
            }
        }
        SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = date.format(new Date());
        MainFunction.saveGroupMessage(um.getUser().getAccount(),um.getGroupAccount(),um.getMessage(),format);
    } //与客户端进行通信

    public void privateChat(ChatMsg cm) throws IOException {   //客户端之间通过账号进行私聊
        UserMsgToUser um = JSON.parseObject(cm.getPrivateMsg(), UserMsgToUser.class);
        System.out.println(um.getDestUser().getAccount());
        if (sockets.containsKey(um.getDestUser().getAccount())) {
            Socket socket1 = sockets.get(um.getDestUser().getAccount());
            DataOutputStream dou1;
            try {

                dou1 = new DataOutputStream(socket1.getOutputStream());

                byte[] bytes = MsgTool.packMsg(cm);
                dou1.write(bytes);
                dou1.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = date.format(new Date());
        MainFunction.saveMessage(um.getSrcUser().getAccount(), um.getDestUser().getAccount(), um.getMessage(), format);
    }

    public void updateMsg(UpdateList ul,Socket socket,String groupAccount,int state) throws IOException {

        byte type = 0x20;
        String group = JSON.toJSONString(ul);
        UpdateListMsg ulm = new UpdateListMsg(9+group.getBytes().length,state,type,group);
        ArrayList<String> members = MainFunction.getMembers(groupAccount);
        byte[] bytes1 = MsgTool.packMsg(ulm);
        for (Map.Entry<String, Socket> entry : sockets.entrySet()) {
            for (int i=0 ; i < members.size();i++) {
                if (!entry.getValue().equals(socket) && entry.getKey().equals(members.get(i))) {
                    DataOutputStream dos1 = new DataOutputStream(entry.getValue().getOutputStream());
                    dos1.write(bytes1);
                    dos1.flush();
                }
            }
        }
    }

    @Override
    public void run() {
        try {
            processClient();

        } catch (IOException e) {
            Server.count--;
            System.out.println("用户："+userAccount+"退出服务器");
            System.out.println("当前在线人数："+Server.count);
        }
    }
}
